/*****************************************************************************
* NewDelete.cpp -  CPP placement new and delete operators implementation
*****************************************************************************
* Copyright (c) Microsoft Corporation All Rights Reserved
*
* Module Name:
*
* NewDelete.cpp
*
* Abstract:
*
*   Definition of placement new and delete operators.
*
*/

#ifdef _NEW_DELETE_OPERATORS_
#ifdef __cplusplus
extern "C" {
#include <wdm.h>
}
#else
#include <wdm.h>
#endif
#include "NewDelete.h"
#include "Globals.h"


#pragma code_seg()
/*****************************************************************************
* Functions
*/

/*****************************************************************************
* ::new()
*****************************************************************************
* New function for creating objects with a specified allocation tag.
*/
PVOID operator new
(
	size_t          iSize,
	_When_((poolType & NonPagedPoolMustSucceed) != 0,
		__drv_reportError("Must succeed pool allocations are forbidden. "
			"Allocation failures cause a system crash"))
	POOL_TYPE       poolType,
	ULONG           tag
	)
{
	PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag);

	if (result)
	{
		RtlZeroMemory(result, iSize);
	}

	return result;
}


/*****************************************************************************
* ::new()
*****************************************************************************
* New function for creating objects with a specified allocation tag.
*/
PVOID operator new
(
	size_t          iSize,
	_When_((poolType & NonPagedPoolMustSucceed) != 0,
		__drv_reportError("Must succeed pool allocations are forbidden. "
			"Allocation failures cause a system crash"))
	POOL_TYPE       poolType
	)
{
	PVOID result = ExAllocatePoolWithTag(poolType, iSize, DRIVER_POOLTAG);

	if (result)
	{
		RtlZeroMemory(result, iSize);
	}

	return result;
}


/*****************************************************************************
* ::delete()
*****************************************************************************
* Delete with tag function.
*/
void __cdecl operator delete
(
	PVOID pVoid,
	ULONG tag
	)
{
	if (pVoid)
	{
		ExFreePoolWithTag(pVoid, tag);
	}
}


/*****************************************************************************
* ::delete()
*****************************************************************************
* Sized Delete function.
*/
void __cdecl operator delete
(
	_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
	_In_ size_t cbSize
	)
{
	UNREFERENCED_PARAMETER(cbSize);

	if (pVoid)
	{
		ExFreePoolWithTag(pVoid, DRIVER_POOLTAG);
	}
}


/*****************************************************************************
* ::delete()
*****************************************************************************
* Sized Array Delete function.
*/
void __cdecl operator delete[]
(
	_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid,
	_In_ size_t cbSize
	)
{
	UNREFERENCED_PARAMETER(cbSize);

	if (pVoid)
	{
		ExFreePoolWithTag(pVoid, DRIVER_POOLTAG);
	}
}


/*****************************************************************************
* ::delete()
*****************************************************************************
* Array Delete function.
*/
void __cdecl operator delete[]
(
	_Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid
	)
{
	if (pVoid)
	{
		ExFreePoolWithTag(pVoid, DRIVER_POOLTAG);
	}
}
#endif//_NEW_DELETE_OPERATORS_
